package com.common.util;

import com.common.baseconstant.MapJson;
import com.common.baseconstant.ResultXml;
import com.common.baseconstant.ReturnCode;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * function
 * Created by Administrator on 2016/12/1.
 */
public class WebExceptionLongHandler extends AbstractHandlerExceptionResolver {
    private String errorViewName;

    private boolean prettyPrint;

    @Override
    protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
                                              Exception ex) {
        if (ex instanceof HttpMessageNotReadableException || ex instanceof HttpRequestMethodNotSupportedException) {
            return new ModelAndView(ResultXml.XML_VIEW_NAME).addObject(new ResultXml(ReturnCode.PARAM_ERROR));
        }
        boolean hasParamErrorForJson = ex instanceof MissingServletRequestParameterException || ex instanceof TypeMismatchException;
        if (hasParamErrorForJson) {
            return buildJsonView(MapJson.PARAM_ERROR_MAP);
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        ResponseBody responseBody = method.getAnnotation(ResponseBody.class);
        if (responseBody != null) {
            String requestContentType = request.getContentType();
            if (requestContentType.contains(MediaType.TEXT_XML_VALUE) ||
                    requestContentType.contains(MediaType.APPLICATION_XML_VALUE) ||
                    requestContentType.contains(MediaType.APPLICATION_XHTML_XML_VALUE) ||
                    requestContentType.contains(MediaType.APPLICATION_ATOM_XML_VALUE)) {
                return new ModelAndView(ResultXml.XML_VIEW_NAME).addObject(new ResultXml(ReturnCode.SYSTEM_ERROR));
            }
            return buildJsonView(MapJson.SYSTEM_ERROR_MAP);
        }
        return new ModelAndView(errorViewName);
    }

    private ModelAndView buildJsonView(Map<String, Object> map) {
        MappingJackson2JsonView mappingJackson2JsonView = new MappingJackson2JsonView();
        mappingJackson2JsonView.setPrettyPrint(prettyPrint);
        mappingJackson2JsonView.setAttributesMap(map);
        return new ModelAndView(mappingJackson2JsonView);
    }

    @Override
    protected void logException(Exception ex, HttpServletRequest request) {
        logger.error("Handler execution resulted in exception>>>", ex);
    }




    public void setErrorViewName(String errorViewName) {
        this.errorViewName = errorViewName;
    }

    public void setPrettyPrint(boolean prettyPrint) {
        this.prettyPrint = prettyPrint;
    }
}
